package com.example.spider.proxy.provider;

import com.example.spider.proxy.core.ProxyInfo;
import com.example.spider.proxy.core.ProxyRepository;
import com.example.spider.task.SpiderResultHandler;
import com.example.spider.task.Task;
import com.example.spider.task.limit.FixWindowLimit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;

import java.time.Duration;

/**
 * 爬虫 ip 代理结果处理器
 *
 * @author lym
 */
public abstract class AbstractProxyResultHandler implements SpiderResultHandler<IpProxySpiderTask, String> {

    static {
        Task.registerType(IpProxySpiderTask.class);
    }

    protected final Logger log = LoggerFactory.getLogger(getClass());

    protected final String taskName;

    @Lazy
    @Autowired
    @Qualifier(ProxyRepository.SOURCE)
    protected ProxyRepository sourceRepository;

    @Lazy
    @Autowired
    @Qualifier(ProxyRepository.USABLE)
    protected ProxyRepository usableRepository;
    @Lazy
    @Autowired
    @Qualifier(ProxyRepository.STABLE)
    protected ProxyRepository stableRepository;

    public AbstractProxyResultHandler(String taskName) {
        this.taskName = taskName;
    }

    @Override
    public <R> boolean canHandle(Task<R> task, R result) {
        return task instanceof IpProxySpiderTask && taskName.equals(((IpProxySpiderTask) task).getIpProxyTaskId());
    }

    /**
     * 处理结果
     *
     * @param result 页面信息
     */
    public void handle(IpProxySpiderTask task, String result) {
        log.debug("prepare handing {}: {}", taskName, task.getUrl());
        try {
            doHandle(task, result);
            log.info("Success process {}: {}", taskName, task.getUrl());
        } catch (Exception e) {
            log.error("Fail process {}: {}", taskName, task.getUrl(), e);
        }
    }

    protected abstract void doHandle(IpProxySpiderTask task, String result);

    protected IpProxySpiderTask createTask(String url) {
        return customizeTask(new IpProxySpiderTask())
                .setIpProxyTaskId(taskName)
                .setLimitStrategy(new FixWindowLimit(taskName, defaultLimitRateDuration()))
                .setUrl(url);
    }

    protected IpProxySpiderTask customizeTask(IpProxySpiderTask task) {
        return task;
    }

    protected Duration defaultLimitRateDuration() {
        return Duration.ofMillis(300);
    }

    protected void addProxyToSourceRepository(ProxyInfo proxyInfo) {
        sourceRepository.add(proxyInfo);
    }

    protected void addProxyToUsableRepository(ProxyInfo proxyInfo) {
        usableRepository.add(proxyInfo);
    }

    protected void addProxyToStableRepository(ProxyInfo proxyInfo) {
        stableRepository.add(proxyInfo);
    }
}
